`include "../define.svh"
//多数据类型乘法器，暂不支持非规格数，NaN，inf类型的浮点数输入
//3.10 问题记录：在运算过程中，如果数据类型更改，输出结果错误；在矩阵运算过程中，一般不会出现类型更改，此问题暂时搁置
//3.20 问题记录：乘法结果输出需要添加握手信号以保证和加法器输入端同步
//3.26 已添加非规格数支持
module FP_Mult 
(
    input clk,
    input sys_rst_n,
    input en,
    input [1:0]data_type,  
    input [`DATA_SIZE-1:0]data_in,
    input mix_precision,
    input [`DATA_SIZE-1:0]weight_in,
    output [`DATA_SIZE-1:0]float_o
);
    wire signed [9:0] e_norm;
    wire [47:0] m_norm;

    wire [8:0]e_out;
    wire s_out;
    wire s1_out,s2_out;
    wire [7:0]e1_out,e2_out;
    wire [47:0]product;
    wire [23:0]m1,m2;
    wire [23:0]m_final;
    wire [7:0]e_final;
    wire [23:0]m_norm_o;
    wire signed [9:0]e_norm_o;

    wire spec_valid;//特殊标志
    wire [7:0]e_out_spec;//特殊结果指数
    wire [22:0]m_out_spec;//特殊结果尾数
    //wire s_out_spec;//特殊结果符号

    wire [23:0] mant_out_reg;
    wire [9:0]exp_out;

    wire s_out_r2,s_out_r3;//符号位寄存器

    wire [5:0]data_shift;


    wire [1:0]post_type,pre_type;   //通过控制各模块的数据类型信号开启FP16-FP32混合精度模式
    assign post_type = (mix_precision)?`FP32 : data_type;
    assign pre_type = (mix_precision)? `FP16 : data_type;




    unpack unpack_inst(
    .data_type(pre_type),  
    .data_in(data_in),
    .weight_in(weight_in),
    .unpack_en(en),
    .s1_reg(s1_out),
    .s2_reg(s2_out),
    .e1_reg(e1_out),
    .e2_reg(e2_out),
    .m1_reg(m1),
    .m2_reg(m2)
);
    Mult_special_case special_case_inst(
    .data_type(pre_type),  // 2'b00:INT4,2'b01:INT8,2'b10:FP16,2'b11:FP32
    .e1(e1_out),
    .e2(e2_out),
    .m1(m1[22:0]),
    .m2(m2[22:0]),
    .e_out(e_out_spec),
    .m_out(m_out_spec),
    .spec_valid(spec_valid)        // valid信号，给下一级模块
);

/*     // 特殊标志和结果的四级流水寄存器
    reg spec_valid_reg1, spec_valid_reg2;
    reg [7:0] e_out_spec_reg1, e_out_spec_reg2;
    reg [22:0] m_out_spec_reg1, m_out_spec_reg2;
 */
/*     // 每级流水线寄存器的更新
    always @(posedge clk) begin
        // 传递 spec_valid
            spec_valid_reg1 <= spec_valid;       // Cycle 1 → Cycle 2
            //spec_valid_reg2 <= spec_valid_reg1;  // Cycle 2 → Cycle 3
            //spec_valid_reg3 <= spec_valid_reg2;  // Cycle 3 → Cycle 4
            //spec_valid_reg4 <= spec_valid_reg3;  // Cycle 4 → 输出

            // 传递 special_result 指数
            e_out_spec_reg1 <= e_out_spec;       // Cycle 1 → Cycle 2
            //e_out_spec_reg2 <= e_out_spec_reg1; // Cycle 2 → Cycle 3
            //e_out_spec_reg3 <= e_out_spec_reg2; // Cycle 3 → Cycle 4
            //e_out_spec_reg4 <= e_out_spec_reg3; // Cycle 4 → 输出

            m_out_spec_reg1 <= m_out_spec;       // Cycle 1 → Cycle 2
            //m_out_spec_reg2 <= m_out_spec_reg1; // Cycle 2 → Cycle 3
            //m_out_spec_reg3 <= m_out_spec_reg2; // Cycle 3 → Cycle 4
            //m_out_spec_reg4 <= m_out_spec_reg3; // Cycle 4 → 输出
    end
 */
    SignAndExp u_SignAndExp(
    .data_type(post_type),
    .mix_precision(mix_precision),
    .e1(e1_out),
    .e2(e2_out),
    .s1(s1_out),
    .s2(s2_out),
    .s_out(s_out),
    .e_out(e_out)
);

    multiply multiply_inst(
    //.clk(clk),
    .m1_in(m1),
    .m2_in(m2),
    .mantissa(product)
);

    lzd #(
    .WIDTH(48)
    ) lzd_inst(
    .data(product),
    .count(data_shift)
);


    normalize norm_inst(
    //.clk(clk),
    //.s_in_r2(s_out),
    .e_in(e_out),
    .m_in(product),
    .data_shift(data_shift),
    .data_type(pre_type),
    .e_norm_stage1(e_norm),
    .m_norm_stage1(m_norm)
    //.s_out_r2(s_out_r2)
);

    round round_inst(
    .m_in(m_norm),
    .e_in(e_norm),
    .data_type(post_type),
    .m_out(m_norm_o),
    .e_out(e_norm_o)
);


    overflow  overflow_inst(
    .data_type(post_type),
    .m_norm_i(m_norm_o),
    .e_norm_i(e_norm_o),
    .e_out_final(e_final),
    .m_out_final(m_final)
);

    mult_out mult_out_inst(
    .clk(clk),
    .sys_rst_n(sys_rst_n),
    .e_final(e_final),
    .m_final(m_final),
    .data_type(post_type),
    .spec_valid(spec_valid),
    .m_spec_in(m_out_spec),
    .e_spec_in(e_out_spec),
    .s_final(s_out),
    .product_o_reg(float_o)
);
endmodule